<?php

class Server {
    private $ws = null;
    protected $first = true;

    public function Start($port) {
        $this->ws = new swoole_server("0.0.0.0", $port, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
        $this->ws->set(array(
            "daemonize" => 0,
            "reactor_num" => 4,
            "worker_num" => 1,
        ));
        $this->ws->on("connect", array($this, "onConnect"));
        $this->ws->on("receive", array($this, "onReceive"));
        $this->ws->on("close", array($this, "onClose"));
        logging::d("Server", "start socket.");
        $this->onInit();
        $this->ws->start();
    }

    protected function firstRef() {
        if (!$this->first) {
            return;
        }
        $this->onFirstRef();
        $this->first = false;
    }

    public function onConnect(swoole_server $server, $fd, $from_id) {
        $info = $server->connection_info($fd);
        logging::d("Server", "client connected on fd $fd, from: " . $info["remote_ip"] . ":" . $info["remote_port"]);
        $this->firstRef();
        $this->onClientConnect($fd, $info["remote_ip"], $info["remote_port"]);
    }

    public function onReceive(swoole_server $server, $fd, $reactor_id, $data) {
        logging::d("Server", "onReceive: " . $data);
        $jsarr = json_decode($data, true);
        $op = $jsarr["op"];
        $data = $jsarr["data"];
        $this->onCommand($fd, $op, $data);
    }

    public function onClose(swoole_server $server, $fd, $reactorId) {
        logging::d("Server", "webserver close: $fd.");
        $this->onClientClose($fd);
    }

    public function send($fd, $op, $data) {
        logging::assert(is_array($data), "data must be an array.");
        $temp = array("op" => $op, "data" => $data);
        $s = json_encode($temp);
        $this->ws->send($fd, $s);
        // logging::d("Server", $s);
        return 0;
    }

    public function broadcast($op, $data) {
        logging::fatal("Server", "broadcast not implemented.");
    }

    public function onInit() {
    }

    protected function onCommand($fd, $op, $data) {
        logging::fatal("Server", "onCommand not implemented.");
    }

    protected function onClientConnect($fd, $ip, $port) {
    }

    protected function onClientClose($fd) {
    }

    protected function onFirstRef() {
    }
};


